package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.article.mapper.ArticleHomeMapper;
import com.heima.article.service.HotArticleSerivice;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.constants.HotArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author brianxia
 * @version 1.0
 * @date 2022-09-23 15:26
 */
@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleSerivice {
    @Autowired
    private ArticleHomeMapper articleHomeMapper;
    @Autowired
    private IWemediaClient wemediaClient;
    @Autowired
    private CacheService cacheService;

    @Override
    public void hotArticle() {

        //1.查询5天之内的文章 数据量不能过大，一般不建议超过几万条
        List<ApArticle> apArticles =
                articleHomeMapper.loadArticleByPublishTime(DateTime.now().minusDays(5).toDate());

        //2.计算文章分值
        List<HotArticleVo> list = computeArticleScore(apArticles);

        //3.将数据缓存到redis中
        saveHotArticleToRedis(list);
    }

    private void saveHotArticleToRedis(List<HotArticleVo> list) {

        //判断集合是否为空
        if(CollectionUtils.isEmpty(list)){
            return;
        }

        //1.将文章分值最高的前30条，缓存到对应的频道中 """
        ResponseResult channels = wemediaClient.channels();
        if(channels != null && Objects.equals(channels.getCode(), AppHttpCodeEnum.SUCCESS.getCode())){
            Object data = channels.getData(); //类型丢失
            String s = JSON.toJSONString(data); //转换成字符串 [{},{}]
            List<WmChannel> wmChannels = JSON.parseArray(s, WmChannel.class); //按需还原对象

            //当前文章数据计算分值最高30个，缓存到上面文章集合中
            for (WmChannel wmChannel : wmChannels) {
//                List<HotArticleVo> hotArticleVos = new ArrayList<>();
//                for (HotArticleVo hotArticleVo : list) {
//                    if(Objects.equals(wmChannel.getId(),hotArticleVo.getChannelId())){
//                        //匹配上了，文章在这个频道下
//                        hotArticleVos.add(hotArticleVo);
//                    }
//                }

                List<HotArticleVo> hotArticleVos = list.stream().filter(x
                        -> Objects.equals(wmChannel.getId(), x.getChannelId())).collect(Collectors.toList());

                if(CollectionUtils.isEmpty(hotArticleVos)){
                    continue;
                }

                //对数据排序 + 取前30条
                List<HotArticleVo> articleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed())
                        .limit(30).collect(Collectors.toList());

                cacheService.set(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC + wmChannel.getId(),
                        JSON.toJSONString(articleVos));
            }

        }

        //2.将所有文章分值最高的前30条，缓存到推荐中
        List<HotArticleVo> articleVos = list.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed())
                .limit(30).collect(Collectors.toList());

        cacheService.set(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC + ArticleConstants.DEFAULT_TAG,
                JSON.toJSONString(articleVos));
    }

    private List<HotArticleVo> computeArticleScore(List<ApArticle> apArticles) {

        ArrayList<HotArticleVo> hotArticleVos = new ArrayList<>();

        if(!CollectionUtils.isEmpty(apArticles)){
            for (ApArticle apArticle : apArticles) {
                HotArticleVo hotArticleVo = new HotArticleVo();
                BeanUtils.copyProperties(apArticle,hotArticleVo);

                Integer score = computeScore(apArticle);
                hotArticleVo.setScore(score);
                hotArticleVos.add(hotArticleVo);

            }
        }

        return hotArticleVos;
    }

    private Integer computeScore(ApArticle apArticle) {

        Integer score = 0;

        //阅读
        if(apArticle.getViews() != null){
            score += apArticle.getViews() * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }

        if(apArticle.getLikes() != null){
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }


        if(apArticle.getComment() != null){
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }


        if(apArticle.getCollection() != null){
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }


        return score;
    }

    public static void main(String[] args) {
        //a.用Calendar
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DAY_OF_MONTH,-5);
        Date time = instance.getTime();
        System.out.println(time);

        //b.使用jdk 1.8之后的localdatetime
        LocalDateTime localDateTime = LocalDateTime.now().minusDays(5);
        System.out.println(localDateTime);

        //c.jdk1.8之前 使用joda-time
        Date date = DateTime.now().minusDays(5).toDate();
        System.out.println(date);


        //远程调用类型丢失问题
        ApArticle apArticle = new ApArticle();
        apArticle.setId(1L);

        ResponseResult responseResult = ResponseResult.okResult(apArticle);

        //A->B服务
        String s = JSON.toJSONString(responseResult);
        //B服务收到还原出对象
        ResponseResult responseResult1 = JSON.parseObject(s, ResponseResult.class);

        Object data = responseResult1.getData(); //JSONObject

        String s1 = JSON.toJSONString(data); //{id:1}
        ApArticle apArticle1 = JSON.parseObject(s1, ApArticle.class);

    }
}
